package com.qiaoba.file.minio.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import com.qiaoba.api.file.core.FileCore;
import com.qiaoba.api.file.entity.vo.FileUploadVO;
import com.qiaoba.api.file.enums.PolicyEnum;
import com.qiaoba.api.file.util.FileUtil;
import com.qiaoba.common.base.exception.ServiceException;
import com.qiaoba.file.minio.config.MinioConfig;
import io.minio.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.Date;
import java.util.UUID;

/**
 * Minio 文件服务实现
 *
 * @author ailanyin
 * @date 2023-09-26 09:16:10
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MinioFileServiceImpl implements FileCore {

    private final MinioClient minioClient;

    @Override
    public FileUploadVO upload(String bucketName, String filename, Long size, InputStream inputStream) {
        createBucket(bucketName);
        // 设置存储对象名称
        String objectName = DateUtil.format(new Date(), "yyyy/MM/dd") + "/" + UUID.randomUUID().toString() + "." + FileUtil.getExtension(filename);
        try {
            // 使用putObject上传一个文件到存储桶中
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    // 文件类型为直接下载
                    .contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE)
                    .stream(inputStream, size, ObjectWriteArgs.MIN_MULTIPART_SIZE).build();
            minioClient.putObject(putObjectArgs);

            FileUploadVO vo = new FileUploadVO();
            vo.setUrl(MinioConfig.endpoint + "/" + bucketName + "/" + objectName);
            vo.setFileName(filename);
            vo.setPath(objectName);
            return vo;
        } catch (Exception e) {
            throw new ServiceException("Minio上传文件失败, 异常信息: " + e.getMessage());
        } finally {
            IoUtil.close(inputStream);
        }
    }

    @Override
    public void delete(String bucketName, String path) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(path).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void createBucket(String bucketName) {
        try {
            // 判断存储桶是否已经存在
            boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exist) {
                // 不存在新建
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
                        .bucket(bucketName)
                        .config(FileUtil.getPolicy(bucketName, PolicyEnum.READ))
                        .build();
                // 设置不需要检验, 即可访问
                minioClient.setBucketPolicy(setBucketPolicyArgs);
            }
        } catch (Exception e) {
            log.error("Minio创建存储桶失败, 异常信息: {}", e.getMessage());
        }
    }

}
